# -*- coding: utf-8 -*-

from odoo import models, fields, api
from odoo.exceptions import ValidationError
import hashlib
import secrets


class DeviceUser(models.Model):
    """Device 独立用户模型 - 完全独立的用户系统"""
    _name = 'device.user'
    _description = 'Device 用户管理'
    _order = 'create_time desc, id desc'
    
    # 基础信息
    username = fields.Char('用户名', required=True, index=True)
    password = fields.Char('密码')
    nick_name = fields.Char('用户昵称')
    email = fields.Char('邮箱')
    phone = fields.Char('手机号')
    avatar = fields.Text('头像', help='Base64编码的头像图片')
    
    # 用户类型
    user_type = fields.Selection([
        ('00', '系统用户'),
        ('01', '注册用户')
    ], string='用户类型', default='00')
    
    # 组织信息
    department_id = fields.Many2one('device.department', '所属部门')
    post_ids = fields.Many2many(
        'device.user.post',
        'device_user_post_relation',
        'device_user_id',
        'post_id',
        string='岗位'
    )
    
    # 角色权限  
    role_assignment_ids = fields.One2many(
        'device.user.role.assignment',
        'device_user_id',
        '角色分配'
    )
    role_ids = fields.Many2many(
        'device.user.role',
        'device_user_role_relation',
        'device_user_id',
        'role_id',
        string='用户角色',
        compute='_compute_role_ids',
        store=True
    )
    
    # 状态信息
    status = fields.Selection([
        ('0', '正常'),
        ('1', '停用')
    ], string='用户状态', default='0')
    
    del_flag = fields.Selection([
        ('0', '存在'),
        ('2', '删除')
    ], string='删除标志', default='0')
    
    # 登录相关
    login_ip = fields.Char('最后登录IP')
    login_date = fields.Datetime('最后登录时间')
    login_count = fields.Integer('登录次数', default=0)
    
    # 密码相关
    password_salt = fields.Char('密码盐值')
    password_hash = fields.Char('密码哈希')
    # 临时字段，用于接收明文密码（不存储）
    password_temp = fields.Char('临时密码', store=False)
    
    # 创建和修改信息
    create_time = fields.Datetime('创建时间', default=fields.Datetime.now)
    update_time = fields.Datetime('更新时间', default=fields.Datetime.now)
    create_by = fields.Char('创建者')
    update_by = fields.Char('更新者')
    
    # 备注
    remark = fields.Text('备注')
    
    # 是否超级管理员
    is_admin = fields.Boolean('超级管理员', default=False)
    
    _sql_constraints = [
        ('username_unique', 'unique(username)', '用户名必须唯一！')
    ]
    
    @api.depends('role_assignment_ids', 'role_assignment_ids.active', 'role_assignment_ids.role_id')
    def _compute_role_ids(self):
        for user in self:
            active_assignments = user.role_assignment_ids.filtered('active')
            user.role_ids = active_assignments.mapped('role_id')
    
    def write(self, vals):
        vals['update_time'] = fields.Datetime.now()
        if self.env.user:
            vals['update_by'] = self.env.user.login
        return super().write(vals)
    
    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            vals['create_time'] = fields.Datetime.now()
            if self.env.user:
                vals['create_by'] = self.env.user.login
            
            # 处理密码加密
            if 'password' in vals:
                password = vals['password']
                # 生成盐值
                salt = secrets.token_hex(16)
                vals['password_salt'] = salt
                # 生成密码哈希
                password_with_salt = password + salt
                vals['password_hash'] = hashlib.sha256(password_with_salt.encode()).hexdigest()
                # 保留明文密码，但设置为空值以避免存储
                vals['password'] = ''
                
        return super().create(vals_list)
    
    def check_password(self, password):
        """验证密码"""
        if not self.password_salt or not self.password_hash:
            return False
        
        password_with_salt = password + self.password_salt
        computed_hash = hashlib.sha256(password_with_salt.encode()).hexdigest()
        return computed_hash == self.password_hash
    
    def set_password(self, password):
        """设置新密码"""
        salt = secrets.token_hex(16)
        password_with_salt = password + salt
        password_hash = hashlib.sha256(password_with_salt.encode()).hexdigest()
        
        self.write({
            'password_salt': salt,
            'password_hash': password_hash
        })
    
    def update_login_info(self, ip_address):
        """更新登录信息"""
        self.write({
            'login_ip': ip_address,
            'login_date': fields.Datetime.now(),
            'login_count': self.login_count + 1
        })
    
    def check_user_permissions(self, permission_code):
        """检查用户是否具有指定权限"""
        if self.is_admin:
            return True
            
        # 获取用户所有角色的权限
        permissions = self.role_ids.mapped('permission_ids')
        return permission_code in permissions.mapped('code')
    
    def get_user_menu_permissions(self):
        """获取用户菜单权限"""
        if self.is_admin:
            return self.env['device.menu.permission'].search([])
            
        return self.role_ids.mapped('menu_permission_ids')
    
    def get_user_data_scope(self):
        """获取用户数据权限范围"""
        if self.is_admin:
            return 'all'
            
        roles = self.role_ids
        if not roles:
            return 'self'
            
        # 取最高权限
        data_scopes = roles.mapped('data_scope')
        if '1' in data_scopes:  # 全部数据权限
            return 'all'
        elif '2' in data_scopes:  # 自定数据权限
            return 'custom'
        elif '3' in data_scopes:  # 部门数据权限
            return 'dept'
        elif '4' in data_scopes:  # 部门及以下数据权限
            return 'dept_and_child'
        else:  # 仅本人数据权限
            return 'self'
    
    def get_data_scope_department_ids(self):
        """获取数据权限部门IDs"""
        data_scope = self.get_user_data_scope()
        
        if data_scope == 'all':
            return self.env['device.department'].search([]).ids
        elif data_scope == 'custom':
            return self.role_ids.mapped('department_ids').ids
        elif data_scope == 'dept':
            return [self.department_id.id] if self.department_id else []
        elif data_scope == 'dept_and_child':
            if self.department_id:
                return self.department_id.get_children_departments().ids + [self.department_id.id]
            return []
        else:  # self
            return []


